home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / vidhrdw / nemesis.c < prev    next >
C/C++ Source or Header  |  2000-05-04  |  36KB  |  1,408 lines

  1. /***************************************************************************
  2.  
  3.   vidhrdw.c
  4.  
  5. ***************************************************************************/
  6.  
  7. #include "driver.h"
  8. #include "vidhrdw/generic.h"
  9. #include <math.h>
  10.  
  11. unsigned char *nemesis_videoram1;
  12. unsigned char *nemesis_videoram2;
  13.  
  14. unsigned char *nemesis_characterram;
  15. unsigned char *nemesis_characterram_gfx;
  16. size_t nemesis_characterram_size;
  17. unsigned char *nemesis_xscroll1,*nemesis_xscroll2,*nemesis_yscroll;
  18. unsigned char *nemesis_yscroll1,*nemesis_yscroll2;
  19.  
  20. static struct osd_bitmap *tmpbitmap2;
  21. static struct osd_bitmap *tmpbitmap3;
  22. static struct osd_bitmap *tmpbitmap4;
  23.  
  24. static unsigned char *video1_dirty;    /* 0x800 chars - foreground */
  25. static unsigned char *video2_dirty;    /* 0x800 chars - background */
  26. static unsigned char *char_dirty;    /* 2048 chars */
  27. static unsigned char *sprite_dirty;    /* 512 sprites */
  28. static unsigned char *sprite3216_dirty;    /* 256 sprites */
  29. static unsigned char *sprite816_dirty;    /* 1024 sprites */
  30. static unsigned char *sprite1632_dirty;    /* 256 sprites */
  31. static unsigned char *sprite3232_dirty;    /* 128 sprites */
  32. static unsigned char *sprite168_dirty;    /* 1024 sprites */
  33. static unsigned char *sprite6464_dirty;    /* 32 sprites */
  34.  
  35. WRITE_HANDLER( nemesis_palette_w )
  36. {
  37.     int r,g,b,bit1,bit2,bit3,bit4,bit5;
  38.  
  39.     COMBINE_WORD_MEM(&paletteram[offset],data);
  40.     data = READ_WORD(&paletteram[offset]);
  41.  
  42.     /* Mish, 30/11/99 - Schematics show the resistor values are:
  43.         300 Ohms
  44.         620 Ohms
  45.         1200 Ohms
  46.         2400 Ohms
  47.         4700 Ohms
  48.  
  49.         So the correct weights per bit are 8, 17, 33, 67, 130
  50.     */
  51.  
  52.     #define MULTIPLIER 8 * bit1 + 17 * bit2 + 33 * bit3 + 67 * bit4 + 130 * bit5
  53.  
  54.     bit1=(data >>  0)&1;
  55.     bit2=(data >>  1)&1;
  56.     bit3=(data >>  2)&1;
  57.     bit4=(data >>  3)&1;
  58.     bit5=(data >>  4)&1;
  59.     r = MULTIPLIER;
  60.     r = pow (r/255.0, 2)*255;
  61.     bit1=(data >>  5)&1;
  62.     bit2=(data >>  6)&1;
  63.     bit3=(data >>  7)&1;
  64.     bit4=(data >>  8)&1;
  65.     bit5=(data >>  9)&1;
  66.     g = MULTIPLIER;
  67.     g = pow (g/255.0, 2)*255;
  68.     bit1=(data >>  10)&1;
  69.     bit2=(data >>  11)&1;
  70.     bit3=(data >>  12)&1;
  71.     bit4=(data >>  13)&1;
  72.     bit5=(data >>  14)&1;
  73.     b = MULTIPLIER;
  74.     b = pow (b/255.0, 2)*255;
  75.  
  76.     palette_change_color(offset / 2,r,g,b);
  77. }
  78.  
  79. WRITE_HANDLER( salamander_palette_w )
  80. {
  81.     int r,g,b;
  82.  
  83.     COMBINE_WORD_MEM(&paletteram[offset],data);
  84.     if (offset%4) offset-=2;
  85.  
  86.     data = ((READ_WORD(&paletteram[offset]) << 8) | READ_WORD(&paletteram[offset+2]))&0xffff;
  87.  
  88.     r = (data >>  0) & 0x1f;
  89.     g = (data >>  5) & 0x1f;
  90.     b = (data >> 10) & 0x1f;
  91.  
  92.     r = (r << 3) | (r >> 2);
  93.     g = (g << 3) | (g >> 2);
  94.     b = (b << 3) | (b >> 2);
  95.  
  96.     palette_change_color(offset / 4,r,g,b);
  97. }
  98.  
  99. READ_HANDLER( nemesis_videoram1_r )
  100. {
  101.     return READ_WORD(&nemesis_videoram1[offset]);
  102. }
  103.  
  104. WRITE_HANDLER( nemesis_videoram1_w )
  105. {
  106.     COMBINE_WORD_MEM(&nemesis_videoram1[offset],data);
  107.     if (offset < 0x1000)
  108.         video1_dirty[offset / 2] = 1;
  109.     else
  110.         video2_dirty[(offset - 0x1000) / 2] = 1;
  111. }
  112.  
  113. READ_HANDLER( nemesis_videoram2_r )
  114. {
  115.     return READ_WORD(&nemesis_videoram2[offset]);
  116. }
  117.  
  118. WRITE_HANDLER( nemesis_videoram2_w )
  119. {
  120.     COMBINE_WORD_MEM(&nemesis_videoram2[offset],data);
  121.     if (offset < 0x1000)
  122.         video1_dirty[offset / 2] = 1;
  123.     else
  124.         video2_dirty[(offset - 0x1000) / 2] = 1;
  125. }
  126.  
  127.  
  128. READ_HANDLER( gx400_xscroll1_r ) { return READ_WORD(&nemesis_xscroll1[offset]);}
  129. READ_HANDLER( gx400_xscroll2_r ) { return READ_WORD(&nemesis_xscroll2[offset]);}
  130. READ_HANDLER( gx400_yscroll_r ) { return READ_WORD(&nemesis_yscroll[offset]);}
  131.  
  132. WRITE_HANDLER( gx400_xscroll1_w ) { COMBINE_WORD_MEM(&nemesis_xscroll1[offset],data);}
  133. WRITE_HANDLER( gx400_xscroll2_w ) { COMBINE_WORD_MEM(&nemesis_xscroll2[offset],data);}
  134. WRITE_HANDLER( gx400_yscroll_w ) { COMBINE_WORD_MEM(&nemesis_yscroll[offset],data);}
  135.  
  136.  
  137. /* we have to straighten out the 16-bit word into bytes for gfxdecode() to work */
  138. READ_HANDLER( nemesis_characterram_r )
  139. {
  140.     int res;
  141.  
  142.     res = READ_WORD(&nemesis_characterram_gfx[offset]);
  143.  
  144.     #ifdef LSB_FIRST
  145.     res = ((res & 0x00ff) << 8) | ((res & 0xff00) >> 8);
  146.     #endif
  147.  
  148.     return res;
  149. }
  150.  
  151. WRITE_HANDLER( nemesis_characterram_w )
  152. {
  153.     int oldword = READ_WORD(&nemesis_characterram_gfx[offset]);
  154.     int newword;
  155.  
  156.     COMBINE_WORD_MEM(&nemesis_characterram[offset],data);    /* this is need so that twinbee can run code in the
  157.                                                                 character RAM */
  158.  
  159.     #ifdef LSB_FIRST
  160.     data = ((data & 0x00ff00ff) << 8) | ((data & 0xff00ff00) >> 8);
  161.     #endif
  162.  
  163.     newword = COMBINE_WORD(oldword,data);
  164.     if (oldword != newword)
  165.     {
  166.         WRITE_WORD(&nemesis_characterram_gfx[offset],newword);
  167.  
  168.         char_dirty[offset / 32] = 1;
  169.         sprite_dirty[offset / 128] = 1;
  170.         sprite3216_dirty[offset / 256] = 1;
  171.         sprite1632_dirty[offset / 256] = 1;
  172.         sprite3232_dirty[offset / 512] = 1;
  173.         sprite168_dirty[offset / 64] = 1;
  174.         sprite816_dirty[offset / 64] = 1;
  175.         sprite6464_dirty[offset / 2048] = 1;
  176.     }
  177. }
  178.  
  179.  
  180.  
  181. /* free the palette dirty array */
  182. void nemesis_vh_stop(void)
  183. {
  184.     osd_free_bitmap(tmpbitmap);
  185.     osd_free_bitmap(tmpbitmap2);
  186.     osd_free_bitmap(tmpbitmap3);
  187.     osd_free_bitmap(tmpbitmap4);
  188.     tmpbitmap=0;
  189.     free (char_dirty);
  190.     free (sprite_dirty);
  191.     free (sprite3216_dirty);
  192.     free (sprite1632_dirty);
  193.     free (sprite3232_dirty);
  194.     free (sprite168_dirty);
  195.     free (sprite816_dirty);
  196.     free (sprite6464_dirty);
  197.     char_dirty = 0;
  198.     free (video1_dirty);
  199.     free (video2_dirty);
  200.     free (nemesis_characterram_gfx);
  201. }
  202.  
  203. /* claim a palette dirty array */
  204. int nemesis_vh_start(void)
  205. {
  206.     if ((tmpbitmap = osd_new_bitmap(2 * Machine->drv->screen_width,Machine->drv->screen_height,Machine->scrbitmap->depth)) == 0)
  207.     {
  208.         nemesis_vh_stop();
  209.         return 1;
  210.     }
  211.  
  212.     if ((tmpbitmap2 = osd_new_bitmap(2 * Machine->drv->screen_width,Machine->drv->screen_height,Machine->scrbitmap->depth)) == 0)
  213.     {
  214.         nemesis_vh_stop();
  215.         return 1;
  216.     }
  217.  
  218.     if ((tmpbitmap3 = osd_new_bitmap(2 * Machine->drv->screen_width,Machine->drv->screen_height,Machine->scrbitmap->depth)) == 0)
  219.     {
  220.         nemesis_vh_stop();
  221.         return 1;
  222.     }
  223.  
  224.     if ((tmpbitmap4 = osd_new_bitmap(2 * Machine->drv->screen_width,Machine->drv->screen_height,Machine->scrbitmap->depth)) == 0)
  225.     {
  226.         nemesis_vh_stop();
  227.         return 1;
  228.     }
  229.  
  230.     char_dirty = malloc(2048);
  231.     if (!char_dirty) {
  232.         nemesis_vh_stop();
  233.         return 1;
  234.     }
  235.     memset(char_dirty,1,2048);
  236.  
  237.     sprite_dirty = malloc(512);
  238.     if (!sprite_dirty) {
  239.         nemesis_vh_stop();
  240.         return 1;
  241.     }
  242.     memset(sprite_dirty,1,512);
  243.  
  244.     sprite3216_dirty = malloc(256);
  245.     if (!sprite3216_dirty) {
  246.         nemesis_vh_stop();
  247.         return 1;
  248.     }
  249.     memset(sprite3216_dirty,1,256);
  250.  
  251.     sprite1632_dirty = malloc(256);
  252.     if (!sprite1632_dirty) {
  253.         nemesis_vh_stop();
  254.         return 1;
  255.     }
  256.     memset(sprite1632_dirty,1,256);
  257.  
  258.     sprite3232_dirty = malloc(128);
  259.     if (!sprite3232_dirty) {
  260.         nemesis_vh_stop();
  261.         return 1;
  262.     }
  263.     memset(sprite3232_dirty,1,128);
  264.  
  265.     sprite168_dirty = malloc(1024);
  266.     if (!sprite168_dirty) {
  267.         nemesis_vh_stop();
  268.         return 1;
  269.     }
  270.     memset(sprite168_dirty,1,1024);
  271.  
  272.     sprite816_dirty = malloc(1024);
  273.     if (!sprite816_dirty) {
  274.         nemesis_vh_stop();
  275.         return 1;
  276.     }
  277.     memset(sprite816_dirty,1,32);
  278.  
  279.     sprite6464_dirty = malloc(32);
  280.     if (!sprite6464_dirty) {
  281.         nemesis_vh_stop();
  282.         return 1;
  283.     }
  284.     memset(sprite6464_dirty,1,32);
  285.  
  286.     video1_dirty = malloc (0x800);
  287.     video2_dirty = malloc (0x800);
  288.     if (!video1_dirty || !video2_dirty)
  289.     {
  290.         nemesis_vh_stop();
  291.         return 1;
  292.     }
  293.     memset(video1_dirty,1,0x800);
  294.     memset(video2_dirty,1,0x800);
  295.  
  296.     nemesis_characterram_gfx = malloc(nemesis_characterram_size);
  297.     if(!nemesis_characterram_gfx)
  298.     {
  299.         nemesis_vh_stop();
  300.         return 1;
  301.     }
  302.     memset(nemesis_characterram_gfx,0,nemesis_characterram_size);
  303.  
  304.     return 0;
  305. }
  306.  
  307.  
  308. /* This is a bit slow, but it works. I'll speed it up later */
  309. static void nemesis_drawgfx_zoomup(struct osd_bitmap *dest,const struct GfxElement *gfx,
  310.         unsigned int code,unsigned int color,int flipx,int flipy,int sx,int sy,
  311.         const struct rectangle *clip,int transparency,int transparent_color,int scale)
  312. {
  313.     int ex,ey,y,start,dy;
  314.     const unsigned char *sd;
  315.     unsigned char *bm;
  316.     int col;
  317.     struct rectangle myclip;
  318.  
  319.     int dda_x=0;
  320.     int dda_y=0;
  321.     int ex_count;
  322.     int ey_count;
  323.     int real_x;
  324.     int ysize;
  325.     int xsize;
  326.     const unsigned short *paldata;    /* ASG 980209 */
  327.     int transmask;
  328.  
  329.     if (!gfx) return;
  330.  
  331.     code %= gfx->total_elements;
  332.     color %= gfx->total_colors;
  333.  
  334.     transmask = 1 << transparent_color;
  335.  
  336.     if ((gfx->pen_usage[code] & ~transmask) == 0)
  337.         /* character is totally transparent, no need to draw */
  338.         return;
  339.  
  340.  
  341.     if (Machine->orientation & ORIENTATION_SWAP_XY)
  342.     {
  343.         int temp;
  344.  
  345.         temp = sx;
  346.         sx = sy;
  347.         sy = temp;
  348.  
  349.         temp = flipx;
  350.         flipx = flipy;
  351.         flipy = temp;
  352.  
  353.         if (clip)
  354.         {
  355.             /* clip and myclip might be the same, so we need a temporary storage */
  356.             temp = clip->min_x;
  357.             myclip.min_x = clip->min_y;
  358.             myclip.min_y = temp;
  359.             temp = clip->max_x;
  360.             myclip.max_x = clip->max_y;
  361.             myclip.max_y = temp;
  362.             clip = &myclip;
  363.         }
  364.     }
  365.     if (Machine->orientation & ORIENTATION_FLIP_X)
  366.     {
  367.         sx = dest->width - gfx->width - sx;
  368.  
  369.         if (clip)
  370.         {
  371.             int temp;
  372.  
  373.             /* clip and myclip might be the same, so we need a temporary storage */
  374.             temp = clip->min_x;
  375.             myclip.min_x = dest->width-1 - clip->max_x;
  376.             myclip.max_x = dest->width-1 - temp;
  377.             myclip.min_y = clip->min_y;
  378.             myclip.max_y = clip->max_y;
  379.             clip = &myclip;
  380.         }
  381.     }
  382.     if (Machine->orientation & ORIENTATION_FLIP_Y)
  383.     {
  384.         sy = dest->height - gfx->height - sy;
  385.  
  386.         if (clip)
  387.         {
  388.             int temp;
  389.  
  390.             myclip.min_x = clip->min_x;
  391.             myclip.max_x = clip->max_x;
  392.             /* clip and myclip might be the same, so we need a temporary storage */
  393.             temp = clip->min_y;
  394.             myclip.min_y = dest->height-1 - clip->max_y;
  395.             myclip.max_y = dest->height-1 - temp;
  396.             clip = &myclip;
  397.         }
  398.     }
  399.  
  400.  
  401.     /* check bounds */
  402.     xsize=gfx->width;
  403.     ysize=gfx->height;
  404.     /* Clipping currently done in code loop */
  405.     ex = sx + xsize -1;
  406.     ey = sy + ysize -1;
  407. /*    if (ex >= dest->width) ex = dest->width-1;
  408.     if (clip && ex > clip->max_x) ex = clip->max_x;
  409.     if (sx > ex) return;
  410.     if (ey >= dest->height) tey = dest->height-1;
  411.     if (clip && ey > clip->max_y) ey = clip->max_y;
  412.     if (sy > ey) return;
  413. */
  414.     /* start = code * gfx->height; */
  415.     if (flipy)    /* Y flip */
  416.     {
  417.         start = code * gfx->height + gfx->height-1;
  418.         dy = -1;
  419.     }
  420.     else        /* normal */
  421.     {
  422.         start = code * gfx->height;
  423.         dy = 1;
  424.     }
  425.  
  426.  
  427.  
  428.     paldata = &gfx->colortable[gfx->color_granularity * color];
  429.  
  430.     if (flipx)    /* X flip */
  431.     {
  432.         if (Machine->orientation & ORIENTATION_FLIP_Y)
  433.             y=sy + ysize -1;
  434.         else
  435.             y=sy;
  436.         dda_y=0x80;
  437.         ey_count=sy;
  438.         do
  439.         {
  440.             if(y>=clip->min_y && y<=clip->max_y)
  441.             {
  442.                 if (Machine->orientation & ORIENTATION_FLIP_X)
  443.                 {
  444.                     bm  = dest->line[y]+sx + xsize -1;
  445.                     real_x=sx + xsize -1;
  446.                 } else {
  447.                     bm  = dest->line[y]+sx;
  448.                     real_x=sx;
  449.                 }
  450.                 sd = (gfx->gfxdata + start * gfx->line_modulo + xsize -1);
  451.                 dda_x=0x80;
  452.                 ex_count=sx;
  453.                 col = *(sd);
  454.                 do
  455.                 {
  456.                     if ((real_x<=clip->max_x) && (real_x>=clip->min_x))
  457.                         if (col != transparent_color) *bm = paldata[col];
  458.                     if (Machine->orientation & ORIENTATION_FLIP_X)
  459.                     {
  460.                         bm--;
  461.                         real_x--;
  462.                     } else {
  463.                         bm++;
  464.                         real_x++;
  465.                     }
  466.                     dda_x-=scale;
  467.                     if(dda_x<=0)
  468.                     {
  469.                         dda_x+=0x80;
  470.                         sd--;
  471.                         ex_count++;
  472.                         col = *(sd);
  473.                     }
  474.                 } while(ex_count <= ex);
  475.             }
  476.             if (Machine->orientation & ORIENTATION_FLIP_Y)
  477.                 y--;
  478.             else
  479.                 y++;
  480.             dda_y-=scale;
  481.             if(dda_y<=0)
  482.             {
  483.                 dda_y+=0x80;
  484.                 start+=dy;
  485.                 ey_count++;
  486.             }
  487.  
  488.         } while(ey_count <= ey);
  489.     }
  490.     else        /* normal */
  491.     {
  492.         if (Machine->orientation & ORIENTATION_FLIP_Y)
  493.             y=sy + ysize -1;
  494.         else
  495.             y=sy;
  496.         dda_y=0x80;
  497.         ey_count=sy;
  498.         do
  499.         {
  500.             if(y>=clip->min_y && y<=clip->max_y)
  501.             {
  502.                 if (Machine->orientation & ORIENTATION_FLIP_X)
  503.                 {
  504.                     bm  = dest->line[y]+sx + xsize -1;
  505.                     real_x=sx + xsize -1;
  506.                 } else {
  507.                     bm  = dest->line[y]+sx;
  508.                     real_x=sx;
  509.                 }
  510.                 sd = (gfx->gfxdata + start * gfx->line_modulo);
  511.                 dda_x=0x80;
  512.                 ex_count=sx;
  513.                 col = *(sd);
  514.                 do
  515.                 {
  516.                     if ((real_x<=clip->max_x) && (real_x>=clip->min_x))
  517.                         if (col != transparent_color) *bm = paldata[col];
  518.                     if (Machine->orientation & ORIENTATION_FLIP_X)
  519.                     {
  520.                         bm--;
  521.                         real_x--;
  522.                     } else {
  523.                         bm++;
  524.                         real_x++;
  525.                     }
  526.                     dda_x-=scale;
  527.                     if(dda_x<=0)
  528.                     {
  529.                         dda_x+=0x80;
  530.                         sd++;
  531.                         ex_count++;
  532.                         col = *(sd);
  533.                     }
  534.                 } while(ex_count <= ex);
  535.             }
  536.             if (Machine->orientation & ORIENTATION_FLIP_Y)
  537.                 y--;
  538.             else
  539.                 y++;
  540.             dda_y-=scale;
  541.             if(dda_y<=0)
  542.             {
  543.                 dda_y+=0x80;
  544.                 start+=dy;
  545.                 ey_count++;
  546.             }
  547.  
  548.         } while(ey_count <= ey);
  549.     }
  550. }
  551.  
  552. /* This is a bit slow, but it works. I'll speed it up later */
  553. static void nemesis_drawgfx_zoomdown(struct osd_bitmap *dest,const struct GfxElement *gfx,
  554.         unsigned int code,unsigned int color,int flipx,int flipy,int sx,int sy,
  555.         const struct rectangle *clip,int transparency,int transparent_color,int scale)
  556. {
  557.     int ex,ey,y,start,dy;
  558.     const unsigned char *sd;
  559.     unsigned char *bm;
  560.     int col;
  561.     struct rectangle myclip;
  562.  
  563.     int dda_x=0;
  564.     int dda_y=0;
  565.     int ex_count;
  566.     int ey_count;
  567.     int real_x;
  568.     int ysize;
  569.     int xsize;
  570.     int transmask;
  571.     const unsigned short *paldata;    /* ASG 980209 */
  572.  
  573.     if (!gfx) return;
  574.  
  575.     code %= gfx->total_elements;
  576.     color %= gfx->total_colors;
  577.  
  578.     transmask = 1 << transparent_color;
  579.     if ((gfx->pen_usage[code] & ~transmask) == 0)
  580.         /* character is totally transparent, no need to draw */
  581.         return;
  582.  
  583.  
  584.     if (Machine->orientation & ORIENTATION_SWAP_XY)
  585.     {
  586.         int temp;
  587.  
  588.         temp = sx;
  589.         sx = sy;
  590.         sy = temp;
  591.  
  592.         temp = flipx;
  593.         flipx = flipy;
  594.         flipy = temp;
  595.  
  596.         if (clip)
  597.         {
  598.             /* clip and myclip might be the same, so we need a temporary storage */
  599.             temp = clip->min_x;
  600.             myclip.min_x = clip->min_y;
  601.             myclip.min_y = temp;
  602.             temp = clip->max_x;
  603.             myclip.max_x = clip->max_y;
  604.             myclip.max_y = temp;
  605.             clip = &myclip;
  606.         }
  607.     }
  608.     if (Machine->orientation & ORIENTATION_FLIP_X)
  609.     {
  610.         sx = dest->width - gfx->width - sx;
  611.  
  612.         if (clip)
  613.         {
  614.             int temp;
  615.  
  616.  
  617.             /* clip and myclip might be the same, so we need a temporary storage */
  618.             temp = clip->min_x;
  619.             myclip.min_x = dest->width-1 - clip->max_x;
  620.             myclip.max_x = dest->width-1 - temp;
  621.             myclip.min_y = clip->min_y;
  622.             myclip.max_y = clip->max_y;
  623.             clip = &myclip;
  624.         }
  625.     }
  626.     if (Machine->orientation & ORIENTATION_FLIP_Y)
  627.     {
  628.         sy = dest->height - gfx->height - sy;
  629.  
  630.         if (clip)
  631.         {
  632.             int temp;
  633.  
  634.             myclip.min_x = clip->min_x;
  635.             myclip.max_x = clip->max_x;
  636.             /* clip and myclip might be the same, so we need a temporary storage */
  637.             temp = clip->min_y;
  638.             myclip.min_y = dest->height-1 - clip->max_y;
  639.             myclip.max_y = dest->height-1 - temp;
  640.             clip = &myclip;
  641.         }
  642.     }
  643.  
  644.  
  645.     /* check bounds */
  646.     xsize=gfx->width;
  647.     ysize=gfx->height;
  648.     ex = sx + xsize -1;
  649.     if (ex >= dest->width) ex = dest->width-1;
  650.     if (clip && ex > clip->max_x) ex = clip->max_x;
  651.     if (sx > ex) return;
  652.     ey = sy + ysize -1;
  653.     if (ey >= dest->height) ey = dest->height-1;
  654.     if (clip && ey > clip->max_y) ey = clip->max_y;
  655.     if (sy > ey) return;
  656.  
  657.     /* start = code * gfx->height; */
  658.     if (flipy)    /* Y flip */
  659.     {
  660.         start = code * gfx->height + gfx->height-1;
  661.         dy = -1;
  662.     }
  663.     else        /* normal */
  664.     {
  665.         start = code * gfx->height;
  666.         dy = 1;
  667.     }
  668.  
  669.  
  670.  
  671.     paldata = &gfx->colortable[gfx->color_granularity * color];
  672.  
  673.     if (flipx)    /* X flip */
  674.     {
  675.         if (Machine->orientation & ORIENTATION_FLIP_Y)
  676.             y=sy + ysize -1;
  677.         else
  678.             y=sy;
  679.         dda_y=0-scale/2;
  680.         for(ey_count=0;ey_count<ysize;ey_count++)
  681.         {
  682.             if(dda_y<0) dda_y+=0x80;
  683.             if(dda_y>=0)
  684.             {
  685.                 dda_y-=scale;
  686.                 if(y>=clip->min_y && y<=clip->max_y)
  687.                 {
  688.                     if (Machine->orientation & ORIENTATION_FLIP_X)
  689.                     {
  690.                         bm  = dest->line[y]+sx + xsize -1;
  691.                         real_x=sx + xsize -1;
  692.                     } else {
  693.                         bm  = dest->line[y]+sx;
  694.                         real_x=sx;
  695.                     }
  696.                     sd = (gfx->gfxdata + start * gfx->line_modulo + xsize -1);
  697.                     dda_x=0-scale/2;
  698.                     for(ex_count=0;ex_count<xsize;ex_count++)
  699.                     {
  700.                         if(dda_x<0) dda_x+=0x80;
  701.                         if(dda_x>=0)
  702.                         {
  703.                             dda_x-=scale;
  704.                             if ((real_x<=clip->max_x) && (real_x>=clip->min_x))
  705.                             {
  706.                                 col = *(sd);
  707.                                 if (col != transparent_color) *bm = paldata[col];
  708.                             }
  709.                             if (Machine->orientation & ORIENTATION_FLIP_X)
  710.                             {
  711.                                 bm--;
  712.                                 real_x--;
  713.                             } else {
  714.                                 bm++;
  715.                                 real_x++;
  716.                             }
  717.                         }
  718.                         sd--;
  719.                     }
  720.                 }
  721.                 if (Machine->orientation & ORIENTATION_FLIP_Y)
  722.                     y--;
  723.                 else
  724.                     y++;
  725.             }
  726.             start+=dy;
  727.         }
  728.  
  729.     }
  730.     else        /* normal */
  731.     {
  732.         if (Machine->orientation & ORIENTATION_FLIP_Y)
  733.             y=sy + ysize -1;
  734.         else
  735.             y=sy;
  736.         dda_y=0-scale/2;
  737.         for(ey_count=0;ey_count<ysize;ey_count++)
  738.         {
  739.             if(dda_y<0) dda_y+=0x80;
  740.             if(dda_y>=0)
  741.             {
  742.                 dda_y-=scale;
  743.                 if(y>=clip->min_y && y<=clip->max_y)
  744.                 {
  745.                     if (Machine->orientation & ORIENTATION_FLIP_X)
  746.                     {
  747.                         bm  = dest->line[y]+sx + xsize -1;
  748.                         real_x=sx + xsize -1;
  749.                     } else {
  750.                         bm  = dest->line[y]+sx;
  751.                         real_x=sx;
  752.                     }
  753.                     sd = (gfx->gfxdata + start * gfx->line_modulo);
  754.                     dda_x=0-scale/2;
  755.                     for(ex_count=0;ex_count<xsize;ex_count++)
  756.                     {
  757.                         if(dda_x<0) dda_x+=0x80;
  758.                         if(dda_x>=0)
  759.                         {
  760.                             dda_x-=scale;
  761.                             if ((real_x<=clip->max_x) && (real_x>=clip->min_x))
  762.                             {
  763.                                 col = *(sd);
  764.                                 if (col != transparent_color) *bm = paldata[col];
  765.                             }
  766.                             if (Machine->orientation & ORIENTATION_FLIP_X)
  767.                             {
  768.                                 bm--;
  769.                                 real_x--;
  770.                             } else {
  771.                                 bm++;
  772.                                 real_x++;
  773.                             }
  774.                         }
  775.                         sd++;
  776.                     }
  777.                 }
  778.                 if (Machine->orientation & ORIENTATION_FLIP_Y)
  779.                     y--;
  780.                 else
  781.                     y++;
  782.             }
  783.             start+=dy;
  784.         }
  785.  
  786.     }
  787. }
  788.  
  789.  
  790. static void draw_sprites(struct osd_bitmap *bitmap)
  791. {
  792.     /*
  793.      *    16 bytes per sprite, in memory from 56000-56fff
  794.      *
  795.      *    byte    0 :    relative priority.
  796.      *    byte    2 :    size (?) value #E0 means not used., bit 0x01 is flipx
  797.                     0xc0 is upper 2 bits of zoom.
  798.                     0x38 is size.
  799.      *     byte    4 :    zoom = 0xff
  800.      *    byte    6 :    low bits sprite code.
  801.      *    byte    8 :    color + hi bits sprite code., bit 0x20 is flipy bit. bit 0x01 is high bit of X pos.
  802.      *    byte    A :    X position.
  803.      *    byte    C :    Y position.
  804.      *     byte    E :    not used.
  805.      */
  806.  
  807.     int adress;    /* start of sprite in spriteram */
  808.     int sx;    /* sprite X-pos */
  809.     int sy;    /* sprite Y-pos */
  810.     int code;    /* start of sprite in obj RAM */
  811.     int color;    /* color of the sprite */
  812.     int flipx,flipy;
  813.     int zoom;
  814.     int char_type;
  815.     int priority;
  816.     int size;
  817.  
  818.     for (priority=0;priority<256;priority++)
  819.     {
  820.         for (adress = 0;adress < spriteram_size;adress += 16)
  821.         {
  822.             if(READ_WORD(&spriteram[adress])!=priority) continue;
  823.  
  824.             code = READ_WORD(&spriteram[adress+6]) + ((READ_WORD(&spriteram[adress+8]) & 0xc0) << 2);
  825.             zoom=READ_WORD(&spriteram[adress+4])&0xff;
  826.             if (zoom != 0xFF || code!=0)
  827.             {
  828.                 size=READ_WORD(&spriteram[adress+2]);
  829.                 zoom+=(size&0xc0)<<2;
  830.  
  831.                 sx = READ_WORD(&spriteram[adress+10])&0xff;
  832.                 sy = READ_WORD(&spriteram[adress+12])&0xff;
  833.                 if(READ_WORD(&spriteram[adress+8])&1) sx-=0x100;    /* fixes left side clip */
  834.                 color = (READ_WORD(&spriteram[adress+8]) & 0x1e) >> 1;
  835.                 flipx = READ_WORD(&spriteram[adress+2]) & 0x01;
  836.                 flipy = READ_WORD(&spriteram[adress+8]) & 0x20;
  837.  
  838.                 switch(size&0x38)
  839.                 {
  840.                     case 0x00:    /* sprite 32x32*/
  841.                         char_type=4;
  842.                         code/=8;
  843.                         break;
  844.                     case 0x08:    /* sprite 16x32 */
  845.                         char_type=5;
  846.                         code/=4;
  847.                         break;
  848.                     case 0x10:    /* sprite 32x16 */
  849.                         char_type=2;
  850.                         code/=4;
  851.                         break;
  852.                     case 0x18:        /* sprite 64x64 */
  853.                         char_type=7;
  854.                         code/=32;
  855.                         break;
  856.                     case 0x20:    /* char 8x8 */
  857.                         char_type=0;
  858.                         code*=2;
  859.                         break;
  860.                     case 0x28:        /* sprite 16x8 */
  861.                         char_type=6;
  862.                         break;
  863.                     case 0x30:    /* sprite 8x16 */
  864.                         char_type=3;
  865.                         break;
  866.                     case 0x38:
  867.                     default:    /* sprite 16x16 */
  868.                         char_type=1;
  869.                         code/=2;
  870.                         break;
  871.                 }
  872.  
  873.                 /*  0x80 == no zoom */
  874.                 if(zoom==0x80)
  875.                 {
  876.                     drawgfx(bitmap,Machine->gfx[char_type],
  877.                             code,
  878.                             color,
  879.                             flipx,flipy,
  880.                             sx,sy,
  881.                             &Machine->drv->visible_area,TRANSPARENCY_PEN,0);
  882.                 }
  883.                 else if(zoom>=0x80)
  884.                 {
  885.                     nemesis_drawgfx_zoomdown(bitmap,Machine->gfx[char_type],
  886.                             code,
  887.                             color,
  888.                             flipx,flipy,
  889.                             sx,sy,
  890.                             &Machine->drv->visible_area,TRANSPARENCY_PEN,0,zoom);
  891.                 }
  892.                 else if(zoom>=0x10)
  893.                 {
  894.                     nemesis_drawgfx_zoomup(bitmap,Machine->gfx[char_type],
  895.                             code,
  896.                             color,
  897.                             flipx,flipy,
  898.                             sx,sy,
  899.                             &Machine->drv->visible_area,TRANSPARENCY_PEN,0,zoom);
  900.                 }
  901.             } /* if sprite */
  902.         } /* for loop */
  903.     } /* priority */
  904. }
  905.  
  906. /******************************************************************************/
  907.  
  908. static void setup_palette(void)
  909. {
  910.     int color,code,i;
  911.     int colmask[0x80];
  912.     int pal_base,offs;
  913.  
  914.     palette_init_used_colors();
  915.  
  916.     pal_base = Machine->drv->gfxdecodeinfo[0].color_codes_start;
  917.     for (color = 0;color < 0x80;color++) colmask[color] = 0;
  918.     for (offs = 0x1000 - 2;offs >= 0;offs -= 2)
  919.     {
  920.         code = READ_WORD (&nemesis_videoram1[offs + 0x1000]) & 0x7ff;
  921.         if (char_dirty[code] == 1)
  922.         {
  923.             decodechar(Machine->gfx[0],code,nemesis_characterram_gfx,
  924.                     Machine->drv->gfxdecodeinfo[0].gfxlayout);
  925.             char_dirty[code] = 2;
  926.         }
  927.         color = READ_WORD (&nemesis_videoram2[offs + 0x1000]) & 0x7f;
  928.         colmask[color] |= Machine->gfx[0]->pen_usage[code];
  929.     }
  930.  
  931.     for (color = 0;color < 0x80;color++)
  932.     {
  933.         if (colmask[color] & (1 << 0))
  934.             palette_used_colors[pal_base + 16 * color] = PALETTE_COLOR_TRANSPARENT;
  935.         for (i = 1;i < 16;i++)
  936.         {
  937.             if (colmask[color] & (1 << i))
  938.                 palette_used_colors[pal_base + 16 * color + i] = PALETTE_COLOR_USED;
  939.         }
  940.     }
  941.  
  942.  
  943.     pal_base = Machine->drv->gfxdecodeinfo[1].color_codes_start;
  944.     for (color = 0;color < 0x80;color++) colmask[color] = 0;
  945.     for (offs = 0;offs < spriteram_size;offs += 16)
  946.     {
  947.         int char_type;
  948.         int zoom=READ_WORD(&spriteram[offs+4]);
  949.         code = READ_WORD(&spriteram[offs+6]) + ((READ_WORD(&spriteram[offs+8]) & 0xc0) << 2);
  950.         if (zoom != 0xFF || code!=0)
  951.         {
  952.             int size=READ_WORD(&spriteram[offs+2]);
  953.             switch(size&0x38)
  954.             {
  955.                 case 0x00:
  956.                     /* sprite 32x32*/
  957.                     char_type=4;
  958.                     code/=8;
  959.                     if (sprite3232_dirty[code] == 1)
  960.                     {
  961.                         decodechar(Machine->gfx[char_type],code,nemesis_characterram_gfx,
  962.                                 Machine->drv->gfxdecodeinfo[char_type].gfxlayout);
  963.                         sprite3232_dirty[code] = 0;
  964.                     }
  965.                     break;
  966.                 case 0x08:
  967.                     /* sprite 16x32 */
  968.                     char_type=5;
  969.                     code/=4;
  970.                     if (sprite1632_dirty[code] == 1)
  971.                     {
  972.                         decodechar(Machine->gfx[char_type],code,nemesis_characterram_gfx,
  973.                                 Machine->drv->gfxdecodeinfo[char_type].gfxlayout);
  974.                         sprite1632_dirty[code] = 0;
  975.  
  976.                     }
  977.                     break;
  978.                 case 0x10:
  979.                     /* sprite 32x16 */
  980.                     char_type=2;
  981.                     code/=4;
  982.                     if (sprite3216_dirty[code] == 1)
  983.                     {
  984.                         decodechar(Machine->gfx[char_type],code,nemesis_characterram_gfx,
  985.                                 Machine->drv->gfxdecodeinfo[char_type].gfxlayout);
  986.                         sprite3216_dirty[code] = 0;
  987.                     }
  988.                     break;
  989.                 case 0x18:
  990.                     /* sprite 64x64 */
  991.                     char_type=7;
  992.                     code/=32;
  993.                     if (sprite6464_dirty[code] == 1)
  994.                     {
  995.                         decodechar(Machine->gfx[char_type],code,nemesis_characterram_gfx,
  996.                                 Machine->drv->gfxdecodeinfo[char_type].gfxlayout);
  997.                         sprite6464_dirty[code] = 0;
  998.                     }
  999.                     break;
  1000.                 case 0x20:
  1001.                     /* char 8x8 */
  1002.                     char_type=0;
  1003.                     code*=2;
  1004.                     if (char_dirty[code] == 1)
  1005.                     {
  1006.                         decodechar(Machine->gfx[char_type],code,nemesis_characterram_gfx,
  1007.                         Machine->drv->gfxdecodeinfo[char_type].gfxlayout);
  1008.                         char_dirty[code] = 0;
  1009.                     }
  1010.                     break;
  1011.                 case 0x28:
  1012.                     /* sprite 16x8 */
  1013.                     char_type=6;
  1014.                     if (sprite168_dirty[code] == 1)
  1015.                     {
  1016.                         decodechar(Machine->gfx[char_type],code,nemesis_characterram_gfx,
  1017.                                 Machine->drv->gfxdecodeinfo[char_type].gfxlayout);
  1018.                         sprite168_dirty[code] = 0;
  1019.                     }
  1020.                     break;
  1021.                 case 0x30:
  1022.                     /* sprite 8x16 */
  1023.                     char_type=3;
  1024.                     if (sprite816_dirty[code] == 1)
  1025.                     {
  1026.                         decodechar(Machine->gfx[char_type],code,nemesis_characterram_gfx,
  1027.                                 Machine->drv->gfxdecodeinfo[char_type].gfxlayout);
  1028.                         sprite816_dirty[code] = 0;
  1029.                     }
  1030.                     break;
  1031.                 default:
  1032.                     logerror("UN-SUPPORTED SPRITE SIZE %-4x\n",size&0x38);
  1033.                 case 0x38:
  1034.                     /* sprite 16x16 */
  1035.                     char_type=1;
  1036.                     code/=2;
  1037.                     if (sprite_dirty[code] == 1)
  1038.                     {
  1039.                         decodechar(Machine->gfx[char_type],code,nemesis_characterram_gfx,
  1040.                                 Machine->drv->gfxdecodeinfo[char_type].gfxlayout);
  1041.                         sprite_dirty[code] = 2;
  1042.  
  1043.                     }
  1044.                     break;
  1045.             }
  1046.  
  1047.             color = (READ_WORD(&spriteram[offs+8]) & 0x1e) >> 1;
  1048.             colmask[color] |= Machine->gfx[char_type]->pen_usage[code];
  1049.         }
  1050.     }
  1051.  
  1052.  
  1053.     for (color = 0;color < 0x80;color++)
  1054.     {
  1055.         if (colmask[color] & (1 << 0))
  1056.             palette_used_colors[pal_base + 16 * color] = PALETTE_COLOR_TRANSPARENT;
  1057.         for (i = 1;i < 16;i++)
  1058.         {
  1059.             if (colmask[color] & (1 << i))
  1060.                 palette_used_colors[pal_base + 16 * color + i] = PALETTE_COLOR_USED;
  1061.         }
  1062.     }
  1063.  
  1064.  
  1065.     pal_base = Machine->drv->gfxdecodeinfo[0].color_codes_start;
  1066.     for (color = 0;color < 0x80;color++) colmask[color] = 0;
  1067.     for (offs = 0x1000 - 2;offs >= 0;offs -= 2)
  1068.     {
  1069.         code = READ_WORD (&nemesis_videoram1[offs]) & 0x7ff;
  1070.         if (char_dirty[code] == 1)
  1071.         {
  1072.             decodechar(Machine->gfx[0],code,nemesis_characterram_gfx,
  1073.                     Machine->drv->gfxdecodeinfo[0].gfxlayout);
  1074.             char_dirty[code] = 2;
  1075.         }
  1076.         color = READ_WORD (&nemesis_videoram2[offs]) & 0x7f;
  1077.         colmask[color] |= Machine->gfx[0]->pen_usage[code];
  1078.     }
  1079.  
  1080.     for (color = 0;color < 0x80;color++)
  1081.     {
  1082.         if (colmask[color] & (1 << 0))
  1083.             palette_used_colors[pal_base + 16 * color] = PALETTE_COLOR_TRANSPARENT;
  1084.         for (i = 1;i < 16;i++)
  1085.         {
  1086.             if (colmask[color] & (1 << i))
  1087.                 palette_used_colors[pal_base + 16 * color + i] = PALETTE_COLOR_USED;
  1088.         }
  1089.     }
  1090.  
  1091.     if (palette_recalc())
  1092.     {
  1093.         memset(video1_dirty,1,0x800);
  1094.         memset(video2_dirty,1,0x800);
  1095.     }
  1096. }
  1097.  
  1098. static void setup_backgrounds(void)
  1099. {
  1100.     int offs;
  1101.  
  1102.     /* Do the foreground first */
  1103.     for (offs = 0x1000 - 2;offs >= 0;offs -= 2)
  1104.     {
  1105.         int code,color;
  1106.  
  1107.  
  1108.         code = READ_WORD (&nemesis_videoram1[offs + 0x1000]) & 0x7ff;
  1109.  
  1110.         if (video2_dirty[offs/2] || char_dirty[code])
  1111.         {
  1112.             int sx,sy,flipx,flipy;
  1113.  
  1114.             color = READ_WORD (&nemesis_videoram2[offs + 0x1000]) & 0x7f;
  1115.  
  1116.             video2_dirty[offs/2] = 0;
  1117.  
  1118.             sx = (offs/2) % 64;
  1119.             sy = (offs/2) / 64;
  1120.             flipx = READ_WORD (&nemesis_videoram2[offs + 0x1000]) & 0x80;
  1121.             flipy =  READ_WORD (&nemesis_videoram1[offs + 0x1000]) & 0x800;
  1122.  
  1123.             if(READ_WORD (&nemesis_videoram1[offs + 0x1000])!=0 || READ_WORD (&nemesis_videoram2[offs + 0x1000])!=0)
  1124.             {
  1125.                 if (READ_WORD(&nemesis_videoram1[offs + 0x1000]) & 0x1000)        //screen priority
  1126.                 {
  1127.                     struct rectangle clip;
  1128.  
  1129.                     drawgfx(tmpbitmap3,Machine->gfx[0],
  1130.                         code,
  1131.                         color,
  1132.                         flipx,flipy,
  1133.                         8*sx,8*sy,
  1134.                         0,TRANSPARENCY_NONE,0);
  1135.  
  1136.                     clip.min_x=8*sx;
  1137.                     clip.max_x=8*sx+7;
  1138.                     clip.min_y=8*sy;
  1139.                     clip.max_y=8*sy+7;
  1140.                     fillbitmap(tmpbitmap,palette_transparent_pen,&clip);
  1141.                 } else {
  1142.                     struct rectangle clip;
  1143.  
  1144.                     drawgfx(tmpbitmap,Machine->gfx[0],
  1145.                         code,
  1146.                         color,
  1147.                         flipx,flipy,
  1148.                         8*sx,8*sy,
  1149.                         0,TRANSPARENCY_NONE,0);
  1150.  
  1151.                     clip.min_x=8*sx;
  1152.                     clip.max_x=8*sx+7;
  1153.                     clip.min_y=8*sy;
  1154.                     clip.max_y=8*sy+7;
  1155.                     fillbitmap(tmpbitmap3,palette_transparent_pen,&clip);
  1156.                 }
  1157.             } else {
  1158.                 struct rectangle clip;
  1159.                 clip.min_x=8*sx;
  1160.                 clip.max_x=8*sx+7;
  1161.                 clip.min_y=8*sy;
  1162.                 clip.max_y=8*sy+7;
  1163.                 fillbitmap(tmpbitmap,palette_transparent_pen,&clip);
  1164.                 fillbitmap(tmpbitmap3,palette_transparent_pen,&clip);
  1165.             }
  1166.         }
  1167.     }
  1168.  
  1169.     /* Background */
  1170.     for (offs = 0x1000 - 2;offs >= 0;offs -= 2)
  1171.     {
  1172.         int code,color;
  1173.  
  1174.  
  1175.         code = READ_WORD (&nemesis_videoram1[offs]) & 0x7ff;
  1176.  
  1177.         if (video1_dirty[offs/2] || char_dirty[code])
  1178.         {
  1179.             int sx,sy,flipx,flipy;
  1180.  
  1181.             video1_dirty[offs/2] = 0;
  1182.  
  1183.             color = READ_WORD (&nemesis_videoram2[offs]) & 0x7f;
  1184.  
  1185.             sx = (offs/2) % 64;
  1186.             sy = (offs/2) / 64;
  1187.             flipx = READ_WORD (&nemesis_videoram2[offs]) & 0x80;
  1188.             flipy = READ_WORD (&nemesis_videoram1[offs]) & 0x800;
  1189.  
  1190.             if(READ_WORD (&nemesis_videoram1[offs])!=0 || READ_WORD (&nemesis_videoram2[offs])!=0)
  1191.             {
  1192.                 if (READ_WORD(&nemesis_videoram1[offs]) & 0x1000)        //screen priority
  1193.                 {
  1194.                     struct rectangle clip;
  1195.  
  1196.                     drawgfx(tmpbitmap4,Machine->gfx[0],
  1197.                         code,
  1198.                         color,
  1199.                         flipx,flipy,
  1200.                         8*sx,8*sy,
  1201.                         0,TRANSPARENCY_NONE,0);
  1202.  
  1203.                     clip.min_x=8*sx;
  1204.                     clip.max_x=8*sx+7;
  1205.                     clip.min_y=8*sy;
  1206.                     clip.max_y=8*sy+7;
  1207.                     fillbitmap(tmpbitmap2,palette_transparent_pen,&clip);
  1208.                 } else {
  1209.                     struct rectangle clip;
  1210.  
  1211.                     drawgfx(tmpbitmap2,Machine->gfx[0],
  1212.                         code,
  1213.                         color,
  1214.                         flipx,flipy,
  1215.                         8*sx,8*sy,
  1216.                         0,TRANSPARENCY_NONE,0);
  1217.  
  1218.                     clip.min_x=8*sx;
  1219.                     clip.max_x=8*sx+7;
  1220.                     clip.min_y=8*sy;
  1221.                     clip.max_y=8*sy+7;
  1222.                     fillbitmap(tmpbitmap4,palette_transparent_pen,&clip);
  1223.                 }
  1224.             } else {
  1225.                 struct rectangle clip;
  1226.                 clip.min_x=8*sx;
  1227.                 clip.max_x=8*sx+7;
  1228.                 clip.min_y=8*sy;
  1229.                 clip.max_y=8*sy+7;
  1230.                 fillbitmap(tmpbitmap2,palette_transparent_pen,&clip);
  1231.                 fillbitmap(tmpbitmap4,palette_transparent_pen,&clip);
  1232.             }
  1233.         }
  1234.     }
  1235. }
  1236.  
  1237. /******************************************************************************/
  1238.  
  1239. void nemesis_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
  1240. {
  1241.     int offs;
  1242.     int xscroll[256],xscroll2[256],yscroll;
  1243.  
  1244.     setup_palette();
  1245.  
  1246.     /* Render backgrounds */
  1247.     setup_backgrounds();
  1248.  
  1249.     /* screen flash */
  1250.     fillbitmap(bitmap,Machine->pens[READ_WORD(&paletteram[0x00]) & 0x7ff],&Machine->drv->visible_area);
  1251.  
  1252.     /* Copy the background bitmap */
  1253.     yscroll = -(READ_WORD(&nemesis_yscroll[0x300]) & 0xff);    /* used on nemesis level 2 */
  1254.     for (offs = 0;offs < 256;offs++)
  1255.     {
  1256.         xscroll2[offs] = -((READ_WORD(&nemesis_xscroll2[2 * offs]) & 0xff) +
  1257.                 ((READ_WORD(&nemesis_xscroll2[0x200 + 2 * offs]) & 1) << 8));
  1258.     }
  1259.     copyscrollbitmap(bitmap,tmpbitmap,256,xscroll2,1,&yscroll,&Machine->drv->visible_area,TRANSPARENCY_PEN,palette_transparent_pen);
  1260.  
  1261.     /* Do the foreground */
  1262.     for (offs = 0;offs < 256;offs++)
  1263.     {
  1264.         xscroll[offs] = -((READ_WORD(&nemesis_xscroll1[2 * offs]) & 0xff) +
  1265.                 ((READ_WORD(&nemesis_xscroll1[0x200 + 2 * offs]) & 1) << 8));
  1266.     }
  1267.     copyscrollbitmap(bitmap,tmpbitmap2,256,xscroll,0,0,&Machine->drv->visible_area,TRANSPARENCY_PEN,palette_transparent_pen);
  1268.  
  1269.     draw_sprites(bitmap);
  1270.  
  1271.     copyscrollbitmap(bitmap,tmpbitmap3,256,xscroll2,1,&yscroll,&Machine->drv->visible_area,TRANSPARENCY_PEN,palette_transparent_pen);
  1272.     copyscrollbitmap(bitmap,tmpbitmap4,256,xscroll,0,0,&Machine->drv->visible_area,TRANSPARENCY_PEN,palette_transparent_pen);
  1273.  
  1274.     for (offs = 0; offs < 2048; offs++)
  1275.     {
  1276.         if (char_dirty[offs] == 2)
  1277.             char_dirty[offs] = 0;
  1278.     }
  1279. }
  1280.  
  1281. void twinbee_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
  1282. {
  1283.     int offs;
  1284.     int xscroll[256],xscroll2[256],yscroll;
  1285.  
  1286.     setup_palette();
  1287.  
  1288.     /* Render backgrounds */
  1289.     setup_backgrounds();
  1290.  
  1291.     /* Copy the background bitmap */
  1292.     yscroll = -(READ_WORD(&nemesis_yscroll[0x300]) & 0xff);    /* used on nemesis level 2 */
  1293.     for (offs = 0;offs < 256;offs++)
  1294.     {
  1295.         xscroll2[offs] = -((READ_WORD(&nemesis_xscroll2[2 * offs]) & 0xff) +
  1296.                 ((READ_WORD(&nemesis_xscroll2[0x200 + 2 * offs]) & 1) << 8));
  1297.     }
  1298.     copyscrollbitmap(bitmap,tmpbitmap,256,xscroll2,1,&yscroll,&Machine->drv->visible_area,TRANSPARENCY_NONE,0);
  1299.  
  1300.     /* Do the foreground */
  1301.     for (offs = 0;offs < 256;offs++)
  1302.     {
  1303.         xscroll[offs] = -((READ_WORD(&nemesis_xscroll1[2 * offs]) & 0xff) +
  1304.                 ((READ_WORD(&nemesis_xscroll1[0x200 + 2 * offs]) & 1) << 8));
  1305.     }
  1306.     copyscrollbitmap(bitmap,tmpbitmap2,256,xscroll,0,0,&Machine->drv->visible_area,TRANSPARENCY_PEN,palette_transparent_pen);
  1307.  
  1308.     if (Machine->orientation & ORIENTATION_SWAP_XY)
  1309.         Machine->orientation ^= ORIENTATION_FLIP_X;
  1310.     else
  1311.         Machine->orientation ^= ORIENTATION_FLIP_Y;
  1312.  
  1313.     draw_sprites(bitmap);
  1314.  
  1315.     if (Machine->orientation & ORIENTATION_SWAP_XY)
  1316.         Machine->orientation ^= ORIENTATION_FLIP_X;
  1317.     else
  1318.         Machine->orientation ^= ORIENTATION_FLIP_Y;
  1319.  
  1320.     copyscrollbitmap(bitmap,tmpbitmap3,256,xscroll2,1,&yscroll,&Machine->drv->visible_area,TRANSPARENCY_PEN,palette_transparent_pen);
  1321.     copyscrollbitmap(bitmap,tmpbitmap4,256,xscroll,0,0,&Machine->drv->visible_area,TRANSPARENCY_PEN,palette_transparent_pen);
  1322.  
  1323.     for (offs = 0; offs < 2048; offs++)
  1324.     {
  1325.         if (char_dirty[offs] == 2)
  1326.             char_dirty[offs] = 0;
  1327.     }
  1328. }
  1329.  
  1330. void salamand_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
  1331. {
  1332.     int offs,l;
  1333.     int xscroll[256],yscroll[256],xscroll2[256],yscroll2[256];
  1334.     int culumn_scroll = 0;
  1335.  
  1336.     setup_palette();
  1337.  
  1338.     /* Render backgrounds */
  1339.     setup_backgrounds();
  1340.  
  1341.     /* screen flash */
  1342.     fillbitmap(bitmap,Machine->pens[READ_WORD(&paletteram[0x00]) & 0x7ff],&Machine->drv->visible_area);
  1343.  
  1344.     /* Kludge - check if we need row or column scroll */
  1345.     if (READ_WORD(&nemesis_yscroll[0x780]) || READ_WORD(&nemesis_yscroll[0x790])) {
  1346.         /* Column scroll */
  1347.         culumn_scroll = 1;
  1348.         l=0;
  1349.         for (offs = 0x800-2;offs >= 0x780; offs-=2)
  1350.         {
  1351.             yscroll[l] = yscroll[l+64] = -READ_WORD(&nemesis_yscroll[offs]);
  1352.             l++;
  1353.         }
  1354.         copyscrollbitmap(bitmap,tmpbitmap2,0,0,128,yscroll,&Machine->drv->visible_area,TRANSPARENCY_PEN,palette_transparent_pen);
  1355.     } else { /* Rowscroll */
  1356.         for (offs = 0;offs < 256;offs++)
  1357.         {
  1358.             xscroll[offs] = -((READ_WORD(&nemesis_xscroll1[2 * offs]) & 0xff) +
  1359.                     ((READ_WORD(&nemesis_xscroll1[0x200 + 2 * offs]) & 1) << 8));
  1360.         }
  1361.         copyscrollbitmap(bitmap,tmpbitmap2,256,xscroll,0,0,&Machine->drv->visible_area,TRANSPARENCY_PEN,palette_transparent_pen);
  1362.     }
  1363.  
  1364.     /* Copy the foreground bitmap */
  1365.     if (READ_WORD(&nemesis_yscroll[0x700]) || READ_WORD(&nemesis_yscroll[0x710])) {
  1366.         /* Column scroll */
  1367.         l=0;
  1368.         for (offs = 0x780-2;offs >= 0x700; offs-=2)
  1369.         {
  1370.             yscroll2[l] = yscroll2[l+64] = -READ_WORD(&nemesis_yscroll[offs]);
  1371.             l++;
  1372.         }
  1373.         copyscrollbitmap(bitmap,tmpbitmap,0,0,128,yscroll2,&Machine->drv->visible_area,TRANSPARENCY_PEN,palette_transparent_pen);
  1374.  
  1375.         draw_sprites(bitmap);
  1376.  
  1377.         if (culumn_scroll)
  1378.             copyscrollbitmap(bitmap,tmpbitmap4,0,0,128,yscroll,&Machine->drv->visible_area,TRANSPARENCY_PEN,palette_transparent_pen);
  1379.         else
  1380.             copyscrollbitmap(bitmap,tmpbitmap4,256,xscroll,0,0,&Machine->drv->visible_area,TRANSPARENCY_PEN,palette_transparent_pen);
  1381.  
  1382.         copyscrollbitmap(bitmap,tmpbitmap3,0,0,128,yscroll2,&Machine->drv->visible_area,TRANSPARENCY_PEN,palette_transparent_pen);
  1383.     } else { /* Rowscroll */
  1384.         for (offs = 0;offs < 256;offs++)
  1385.         {
  1386.             xscroll2[offs] = -((READ_WORD(&nemesis_xscroll2[2 * offs]) & 0xff) +
  1387.                     ((READ_WORD(&nemesis_xscroll2[0x200 + 2 * offs]) & 1) << 8));
  1388.         }
  1389.         copyscrollbitmap(bitmap,tmpbitmap,256,xscroll2,0,0,&Machine->drv->visible_area,TRANSPARENCY_PEN,palette_transparent_pen);
  1390.  
  1391.         draw_sprites(bitmap);
  1392.  
  1393.         if (culumn_scroll)
  1394.             copyscrollbitmap(bitmap,tmpbitmap4,0,0,128,yscroll,&Machine->drv->visible_area,TRANSPARENCY_PEN,palette_transparent_pen);
  1395.         else
  1396.             copyscrollbitmap(bitmap,tmpbitmap4,256,xscroll,0,0,&Machine->drv->visible_area,TRANSPARENCY_PEN,palette_transparent_pen);
  1397.  
  1398.         copyscrollbitmap(bitmap,tmpbitmap3,256,xscroll2,0,0,&Machine->drv->visible_area,TRANSPARENCY_PEN,palette_transparent_pen);
  1399.     }
  1400.  
  1401.     for (offs = 0; offs < 2048; offs++)
  1402.     {
  1403.         if (char_dirty[offs] == 2)
  1404.             char_dirty[offs] = 0;
  1405.     }
  1406. }
  1407.  
  1408.